package helper.base.math

import helper.base.A2LHM
import helper.base.list.ArrayListHelper.ArrayListExpand.mathMinus
import helper.base.list.ArrayListHelper.ArrayListExpand.toCovarianceMatrix
import helper.base.RandomHelper.Expand.getRandomE
import helper.base.math.MathHelper.MapListMerger.getCombinedProductMap
import helper.scxml.scxml2.MathHelper.DoubleArrayArrayExpand.toDoubleArrayArray
import helper.scxml.strategy.StrategyHelper.TimedEventHelper.TimedEvent.Companion.makeTimedEvent
import helper.scxml.strategy.StrategyHelper.TimedEventHelper.TimedEvent.Expand.getCombinedProductMap
import org.junit.Assert.assertEquals
import org.junit.Test

internal class MathHelperTest {
    @Test
    fun t1() {
        val a1 = arrayListOf(1.0, 2.0, 4.0)
        val a2 = arrayListOf(2.0, 4.0, 8.0)
        val a3 = a1.mathMinus(a2)
        println(a3)
        //[-1.0, -2.0, -4.0]
    }

    @Test
    fun t2() {
        repeat(10000) {
            linkedMapOf(
                "s1s2" to 1.0,
                "s1s3" to 1.0,
                "s1s4t1" to 1.0,
            ).let {
                if (it.getRandomE() == null) {
                    println("randomString is null")
                }
            }
        }
    }

    @Test
    fun t3t1() {
        val data = arrayListOf(
            arrayListOf(2.0, 1.0),
            arrayListOf(4.0, 3.0),
            arrayListOf(6.0, 5.0),
        )
        val covMatrix = data.toCovarianceMatrix()
        println("协方差矩阵:")
        for (row in covMatrix) {
            println(row.joinToString(", "))
        }
        //协方差矩阵:
        //4.0, 4.0
        //4.0, 4.0
    }

    @Test
    fun t3t2() {
        val data = arrayListOf(
            arrayListOf(2.0, 1.0, 10.0),
            arrayListOf(4.0, 3.0, 8.0),
            arrayListOf(6.0, 5.0, 6.0),
            arrayListOf(8.0, 7.0, 4.0),
            arrayListOf(10.0, 9.0, 2.0),
        )
        val covMatrix = data.toCovarianceMatrix()
        println("协方差矩阵:")
        for (row in covMatrix) {
            println(row.joinToString(", "))
        }
        //协方差矩阵:
        //10.0, 10.0, -10.0
        //10.0, 10.0, -10.0
        //-10.0, -10.0, 10.0
    }

    @Test
    fun t4() {
        // 创建一个 DoubleArrayListArrayList
        val data = arrayListOf(
            arrayListOf(1.0, 2.0), arrayListOf(3.0, 4.0)
        )

        // 使用扩展函数进行转换
        val doubleArrayData = data.toDoubleArrayArray()

        // 验证转换结果
        for (i in data.indices) {
            for (j in data[i].indices) {
                assert(doubleArrayData[i][j] == data[i][j]) {
                    "转换错误：位置($i, $j) 的值不匹配"
                }
            }
        }

        println("测试通过！")
    }

    @Test
    fun t5() {
        val number1 = 4.0
        val number2 = 3.4000
        val number3 = 520.0

        MathHelper.printDoubleWithoutTrailingZeros(number1) // 输出：4
        MathHelper.printDoubleWithoutTrailingZeros(number2) // 输出：3.4
        MathHelper.printDoubleWithoutTrailingZeros(number3) // 输出：520
    }

    //2*2*3
    @Test
    fun t_getCombinedProductMap_t1() {
        val aLHM1: A2LHM<String, Double> = linkedMapOf(
            "11" to 1.0,
            "12" to 2.0,
        )

        val aLHM2: A2LHM<String, Double> = linkedMapOf(
            "23" to 3.0,
            "24" to 4.0,
        )
        val aLHM3: A2LHM<String, Double> = linkedMapOf(
            "35" to 5.0,
            "36" to 6.0,
            "37" to 7.0,
        )

        val aEDLHMList = arrayListOf(aLHM1, aLHM2, aLHM3)
        val res = getCombinedProductMap(aEDLHMList)

        // 创建一个预期的输出结果
        val expected = linkedMapOf(
            listOf("11", "23", "35") to 15.0,
            listOf("11", "23", "36") to 18.0,
            listOf("11", "23", "37") to 21.0,
            listOf("11", "24", "35") to 20.0,
            listOf("11", "24", "36") to 24.0,
            listOf("11", "24", "37") to 28.0,
            listOf("12", "23", "35") to 30.0,
            listOf("12", "23", "36") to 36.0,
            listOf("12", "23", "37") to 42.0,
            listOf("12", "24", "35") to 40.0,
            listOf("12", "24", "36") to 48.0,
            listOf("12", "24", "37") to 56.0,
        )

        // 断言
        assertEquals(expected, res)
        for ((k, v) in res) {
            println("Key: $k, Value: $v")
        }
    }

    //2*2*2*2
    @Test
    fun t_getCombinedProductMap_t2() {
        val aLHM1: A2LHM<String, Double> = linkedMapOf(
            "A1" to 1.0,
            "A2" to 2.0,
        )

        val aLHM2: A2LHM<String, Double> = linkedMapOf(
            "B3" to 3.0,
            "B4" to 4.0,
        )

        val aLHM3: A2LHM<String, Double> = linkedMapOf(
            "C5" to 5.0,
            "C6" to 6.0,
        )

        val aLHM4: A2LHM<String, Double> = linkedMapOf(
            "D7" to 7.0,
            "D8" to 8.0,
        )

        val aEDLHMList = arrayListOf(aLHM1, aLHM2, aLHM3, aLHM4)
        val res = getCombinedProductMap(aEDLHMList)

        val expected = linkedMapOf(
            listOf("A1", "B3", "C5", "D7") to 105.0,
            listOf("A1", "B3", "C5", "D8") to 120.0,
            listOf("A1", "B3", "C6", "D7") to 126.0,
            listOf("A1", "B3", "C6", "D8") to 144.0,
            listOf("A1", "B4", "C5", "D7") to 140.0,
            listOf("A1", "B4", "C5", "D8") to 160.0,
            listOf("A1", "B4", "C6", "D7") to 168.0,
            listOf("A1", "B4", "C6", "D8") to 192.0,
            listOf("A2", "B3", "C5", "D7") to 210.0,
            listOf("A2", "B3", "C5", "D8") to 240.0,
            listOf("A2", "B3", "C6", "D7") to 252.0,
            listOf("A2", "B3", "C6", "D8") to 288.0,
            listOf("A2", "B4", "C5", "D7") to 280.0,
            listOf("A2", "B4", "C5", "D8") to 320.0,
            listOf("A2", "B4", "C6", "D7") to 336.0,
            listOf("A2", "B4", "C6", "D8") to 384.0,
        )

        assertEquals(expected, res)

        for ((k, v) in res) {
            println("Key: $k, Value: $v")
        }
    }

    //2*3*4*5
    @Test
    fun t_getCombinedProductMap_t3() {
        val aLHM1 = linkedMapOf(
            makeTimedEvent(1, "E1") to 1.0,
            makeTimedEvent(2, "E2") to 2.0,
        )
        val aLHM2 = linkedMapOf(
            makeTimedEvent(3, "E3") to 3.0,
            makeTimedEvent(4, "E4") to 4.0,
            makeTimedEvent(5, "E5") to 5.0,
        )
        val aLHM3 = linkedMapOf(
            makeTimedEvent(6, "E6") to 6.0,
            makeTimedEvent(7, "E7") to 7.0,
            makeTimedEvent(8, "E8") to 8.0,
            makeTimedEvent(9, "E9") to 9.0,
        )
        val aLHM4 = linkedMapOf(
            makeTimedEvent(10, "E10") to 10.0,
            makeTimedEvent(11, "E11") to 11.0,
            makeTimedEvent(12, "E12") to 12.0,
            makeTimedEvent(13, "E13") to 13.0,
            makeTimedEvent(14, "E14") to 14.0,
        )

        val aEDLHMList = arrayListOf(aLHM1, aLHM2, aLHM3, aLHM4)
        val res = aEDLHMList.getCombinedProductMap()

        // 输出，用于调试。
        for ((k, v) in res) {
            println("Key: $k, Value: $v")
        }
        """
Key: [(1,E1), (3,E3), (6,E6), (10,E10)], Value: 180.0
Key: [(1,E1), (3,E3), (6,E6), (11,E11)], Value: 198.0
Key: [(1,E1), (3,E3), (6,E6), (12,E12)], Value: 216.0
Key: [(1,E1), (3,E3), (6,E6), (13,E13)], Value: 234.0
Key: [(1,E1), (3,E3), (6,E6), (14,E14)], Value: 252.0
Key: [(1,E1), (3,E3), (7,E7), (10,E10)], Value: 210.0
Key: [(1,E1), (3,E3), (7,E7), (11,E11)], Value: 231.0
Key: [(1,E1), (3,E3), (7,E7), (12,E12)], Value: 252.0
Key: [(1,E1), (3,E3), (7,E7), (13,E13)], Value: 273.0
Key: [(1,E1), (3,E3), (7,E7), (14,E14)], Value: 294.0
Key: [(1,E1), (3,E3), (8,E8), (10,E10)], Value: 240.0
Key: [(1,E1), (3,E3), (8,E8), (11,E11)], Value: 264.0
Key: [(1,E1), (3,E3), (8,E8), (12,E12)], Value: 288.0
Key: [(1,E1), (3,E3), (8,E8), (13,E13)], Value: 312.0
Key: [(1,E1), (3,E3), (8,E8), (14,E14)], Value: 336.0
Key: [(1,E1), (3,E3), (9,E9), (10,E10)], Value: 270.0
Key: [(1,E1), (3,E3), (9,E9), (11,E11)], Value: 297.0
Key: [(1,E1), (3,E3), (9,E9), (12,E12)], Value: 324.0
Key: [(1,E1), (3,E3), (9,E9), (13,E13)], Value: 351.0
Key: [(1,E1), (3,E3), (9,E9), (14,E14)], Value: 378.0
Key: [(1,E1), (4,E4), (6,E6), (10,E10)], Value: 240.0
Key: [(1,E1), (4,E4), (6,E6), (11,E11)], Value: 264.0
Key: [(1,E1), (4,E4), (6,E6), (12,E12)], Value: 288.0
Key: [(1,E1), (4,E4), (6,E6), (13,E13)], Value: 312.0
Key: [(1,E1), (4,E4), (6,E6), (14,E14)], Value: 336.0
Key: [(1,E1), (4,E4), (7,E7), (10,E10)], Value: 280.0
Key: [(1,E1), (4,E4), (7,E7), (11,E11)], Value: 308.0
Key: [(1,E1), (4,E4), (7,E7), (12,E12)], Value: 336.0
Key: [(1,E1), (4,E4), (7,E7), (13,E13)], Value: 364.0
Key: [(1,E1), (4,E4), (7,E7), (14,E14)], Value: 392.0
Key: [(1,E1), (4,E4), (8,E8), (10,E10)], Value: 320.0
Key: [(1,E1), (4,E4), (8,E8), (11,E11)], Value: 352.0
Key: [(1,E1), (4,E4), (8,E8), (12,E12)], Value: 384.0
Key: [(1,E1), (4,E4), (8,E8), (13,E13)], Value: 416.0
Key: [(1,E1), (4,E4), (8,E8), (14,E14)], Value: 448.0
Key: [(1,E1), (4,E4), (9,E9), (10,E10)], Value: 360.0
Key: [(1,E1), (4,E4), (9,E9), (11,E11)], Value: 396.0
Key: [(1,E1), (4,E4), (9,E9), (12,E12)], Value: 432.0
Key: [(1,E1), (4,E4), (9,E9), (13,E13)], Value: 468.0
Key: [(1,E1), (4,E4), (9,E9), (14,E14)], Value: 504.0
Key: [(1,E1), (5,E5), (6,E6), (10,E10)], Value: 300.0
Key: [(1,E1), (5,E5), (6,E6), (11,E11)], Value: 330.0
Key: [(1,E1), (5,E5), (6,E6), (12,E12)], Value: 360.0
Key: [(1,E1), (5,E5), (6,E6), (13,E13)], Value: 390.0
Key: [(1,E1), (5,E5), (6,E6), (14,E14)], Value: 420.0
Key: [(1,E1), (5,E5), (7,E7), (10,E10)], Value: 350.0
Key: [(1,E1), (5,E5), (7,E7), (11,E11)], Value: 385.0
Key: [(1,E1), (5,E5), (7,E7), (12,E12)], Value: 420.0
Key: [(1,E1), (5,E5), (7,E7), (13,E13)], Value: 455.0
Key: [(1,E1), (5,E5), (7,E7), (14,E14)], Value: 490.0
Key: [(1,E1), (5,E5), (8,E8), (10,E10)], Value: 400.0
Key: [(1,E1), (5,E5), (8,E8), (11,E11)], Value: 440.0
Key: [(1,E1), (5,E5), (8,E8), (12,E12)], Value: 480.0
Key: [(1,E1), (5,E5), (8,E8), (13,E13)], Value: 520.0
Key: [(1,E1), (5,E5), (8,E8), (14,E14)], Value: 560.0
Key: [(1,E1), (5,E5), (9,E9), (10,E10)], Value: 450.0
Key: [(1,E1), (5,E5), (9,E9), (11,E11)], Value: 495.0
Key: [(1,E1), (5,E5), (9,E9), (12,E12)], Value: 540.0
Key: [(1,E1), (5,E5), (9,E9), (13,E13)], Value: 585.0
Key: [(1,E1), (5,E5), (9,E9), (14,E14)], Value: 630.0
Key: [(2,E2), (3,E3), (6,E6), (10,E10)], Value: 360.0
Key: [(2,E2), (3,E3), (6,E6), (11,E11)], Value: 396.0
Key: [(2,E2), (3,E3), (6,E6), (12,E12)], Value: 432.0
Key: [(2,E2), (3,E3), (6,E6), (13,E13)], Value: 468.0
Key: [(2,E2), (3,E3), (6,E6), (14,E14)], Value: 504.0
Key: [(2,E2), (3,E3), (7,E7), (10,E10)], Value: 420.0
Key: [(2,E2), (3,E3), (7,E7), (11,E11)], Value: 462.0
Key: [(2,E2), (3,E3), (7,E7), (12,E12)], Value: 504.0
Key: [(2,E2), (3,E3), (7,E7), (13,E13)], Value: 546.0
Key: [(2,E2), (3,E3), (7,E7), (14,E14)], Value: 588.0
Key: [(2,E2), (3,E3), (8,E8), (10,E10)], Value: 480.0
Key: [(2,E2), (3,E3), (8,E8), (11,E11)], Value: 528.0
Key: [(2,E2), (3,E3), (8,E8), (12,E12)], Value: 576.0
Key: [(2,E2), (3,E3), (8,E8), (13,E13)], Value: 624.0
Key: [(2,E2), (3,E3), (8,E8), (14,E14)], Value: 672.0
Key: [(2,E2), (3,E3), (9,E9), (10,E10)], Value: 540.0
Key: [(2,E2), (3,E3), (9,E9), (11,E11)], Value: 594.0
Key: [(2,E2), (3,E3), (9,E9), (12,E12)], Value: 648.0
Key: [(2,E2), (3,E3), (9,E9), (13,E13)], Value: 702.0
Key: [(2,E2), (3,E3), (9,E9), (14,E14)], Value: 756.0
Key: [(2,E2), (4,E4), (6,E6), (10,E10)], Value: 480.0
Key: [(2,E2), (4,E4), (6,E6), (11,E11)], Value: 528.0
Key: [(2,E2), (4,E4), (6,E6), (12,E12)], Value: 576.0
Key: [(2,E2), (4,E4), (6,E6), (13,E13)], Value: 624.0
Key: [(2,E2), (4,E4), (6,E6), (14,E14)], Value: 672.0
Key: [(2,E2), (4,E4), (7,E7), (10,E10)], Value: 560.0
Key: [(2,E2), (4,E4), (7,E7), (11,E11)], Value: 616.0
Key: [(2,E2), (4,E4), (7,E7), (12,E12)], Value: 672.0
Key: [(2,E2), (4,E4), (7,E7), (13,E13)], Value: 728.0
Key: [(2,E2), (4,E4), (7,E7), (14,E14)], Value: 784.0
Key: [(2,E2), (4,E4), (8,E8), (10,E10)], Value: 640.0
Key: [(2,E2), (4,E4), (8,E8), (11,E11)], Value: 704.0
Key: [(2,E2), (4,E4), (8,E8), (12,E12)], Value: 768.0
Key: [(2,E2), (4,E4), (8,E8), (13,E13)], Value: 832.0
Key: [(2,E2), (4,E4), (8,E8), (14,E14)], Value: 896.0
Key: [(2,E2), (4,E4), (9,E9), (10,E10)], Value: 720.0
Key: [(2,E2), (4,E4), (9,E9), (11,E11)], Value: 792.0
Key: [(2,E2), (4,E4), (9,E9), (12,E12)], Value: 864.0
Key: [(2,E2), (4,E4), (9,E9), (13,E13)], Value: 936.0
Key: [(2,E2), (4,E4), (9,E9), (14,E14)], Value: 1008.0
Key: [(2,E2), (5,E5), (6,E6), (10,E10)], Value: 600.0
Key: [(2,E2), (5,E5), (6,E6), (11,E11)], Value: 660.0
Key: [(2,E2), (5,E5), (6,E6), (12,E12)], Value: 720.0
Key: [(2,E2), (5,E5), (6,E6), (13,E13)], Value: 780.0
Key: [(2,E2), (5,E5), (6,E6), (14,E14)], Value: 840.0
Key: [(2,E2), (5,E5), (7,E7), (10,E10)], Value: 700.0
Key: [(2,E2), (5,E5), (7,E7), (11,E11)], Value: 770.0
Key: [(2,E2), (5,E5), (7,E7), (12,E12)], Value: 840.0
Key: [(2,E2), (5,E5), (7,E7), (13,E13)], Value: 910.0
Key: [(2,E2), (5,E5), (7,E7), (14,E14)], Value: 980.0
Key: [(2,E2), (5,E5), (8,E8), (10,E10)], Value: 800.0
Key: [(2,E2), (5,E5), (8,E8), (11,E11)], Value: 880.0
Key: [(2,E2), (5,E5), (8,E8), (12,E12)], Value: 960.0
Key: [(2,E2), (5,E5), (8,E8), (13,E13)], Value: 1040.0
Key: [(2,E2), (5,E5), (8,E8), (14,E14)], Value: 1120.0
Key: [(2,E2), (5,E5), (9,E9), (10,E10)], Value: 900.0
Key: [(2,E2), (5,E5), (9,E9), (11,E11)], Value: 990.0
Key: [(2,E2), (5,E5), (9,E9), (12,E12)], Value: 1080.0
Key: [(2,E2), (5,E5), (9,E9), (13,E13)], Value: 1170.0
Key: [(2,E2), (5,E5), (9,E9), (14,E14)], Value: 1260.0
        """.trimIndent()
    }

    @Test
    fun t_getCombinedProductMap_t4() {
        val aLHM1: A2LHM<String, Double> = linkedMapOf(
            "A1" to 1.0,
            "A2" to 2.0
        )

        val aLHM2: A2LHM<String, Double> = linkedMapOf()  // 空的 A2LHM

        val aLHM3: A2LHM<String, Double> = linkedMapOf(
            "C1" to 1.0,
            "C2" to 2.0,
            "C3" to 3.0
        )

        val aLHM4: A2LHM<String, Double> = linkedMapOf(
            "D1" to 1.0,
            "D2" to 2.0
        )

        val aEDLHMList = arrayListOf(aLHM1, aLHM2, aLHM3, aLHM4)
        val res = getCombinedProductMap(aEDLHMList)

        // 输出，用于调试。
        for ((k, v) in res) {
            println("Key: $k, Value: $v")
        }
    }
}